let utils = require('./utils')
let path = require('path')
let Mock = require('mockjs')
let express = require('express')
let bodyParser = require('body-parser')

let app = express()
// view engine setup
app.set('views', path.join(__dirname, 'views'))
// app.set('view engine', 'jade');
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))

const port = 3000
const stdout = false
const file = 'access.log'
const origin = 'http://localhost:8080'

utils.setupExpressLog(app, stdout, file)

app.all('*', function (req, res, next) {
  res.header('Access-Control-Allow-Origin', origin)
  res.header('Access-Control-Allow-Credentials', 'true')
  res.header('Access-Control-Allow-Headers',
      'Content-Type,Content-Length, Authorization, Accept, X-Requested-With')
  res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS')

  if ('OPTIONS' === req.method) {
    res.send(200)
  } else {
    next()
  }
})

let list = []

let handleRequest = (q, s, json, raw = false, api, action) => {
  const isAjax = undefined === q.headers['accept'] ||
      q.headers['accept'].indexOf('text/html') < 0

  const data = 'GET' === q.method ? q.query : q.body
  const type = undefined !== data ? data.type : null

  if (isAjax) {
    s.setHeader('content-type', 'application/json;charset=utf8')
    s.end(utils.mockJson(json, type))
  } else {
    let renderData = {
      api: api,
      action: action,
    };
    if (raw) {
      renderData.html = utils.beautifyJson(json)
    } else {
      renderData.html = utils.mockJsonHtml(json, type)
    }
    s.render('detail', renderData);
  }
}

utils.ls("mocks", list)
list.forEach(function (v) {
  let path = v.substring(5, v.lastIndexOf("."))
  let json = null

  try {
    json = JSON.parse(utils.read(v))
  } catch (e) {
    throw Error('bad mock in:' + v)
  }

  utils.regJson(json)

  let route = express.Router()

  route.all('/', function (q, s) {
    handleRequest(q, s, json.res)
  })

  route.all('/:action', function (q, s) {
    let j = json
    let raw = false

    q.params.action = q.params.action ? q.params.action : "res"
    switch (q.params.action) {
      case "req":
        j = json.req
        break

      case "res":
        j = json.res
        break

      case "raw":
      default:
        raw = true
        break
    }

    handleRequest(q, s, j, raw, path, q.params.action)
  })

  app.use(path, route)
  app.use(bodyParser.json())
})

app.get('/', function (req, res) {
  let data = list.map(function (v) {
    let api = v.replace(/mocks(\S+).json/, '$1')
    return api
  })
  res.render('index', {
    data: data,
  });
})

app.post('/getHtml', function (req, res) {
  var action = req.body.action || 'res'
  var api = req.body.api

  var raw = false
  var json = null
  var path = 'mocks' + api + '.json'

  try {
    json = JSON.parse(utils.read(path))
  } catch (e) {
    throw Error('bad mock in:' + path)
  }

  if (json) {
    switch (action) {
      case "req":
        json = json.req
        break

      case "res":
        json = json.res
        break

      case "raw":
      default:
        raw = true
        break
    }
    var renderData = {}
    if (raw) {
      renderData.html = utils.beautifyJson(json)
    } else {
      renderData.html = utils.mockJsonHtml(json)
    }
    res.setHeader('content-type', 'application/json;charset=utf8')
    res.send(renderData);
  }
})

app.get('/html/:data', function (req, res) {
  var data = req.params.data
  var api = data.replace(/\*/g, '/')

  res.render('detail', {
    api: api,
  })
})

app.post('/post', function (req, res) {

  var base = req.body.base
  var api = req.body.api
  var number = req.body.number || 1

  var data = null
  var json = null
  var mockJson = null
  var path = 'mocks' + api + '.json'

  try {
    json = JSON.parse(utils.read(path))
  } catch (e) {
    throw Error('bad mock in:' + path)
  }
  var dataArr = []
  for (var i = 0; i < number; i++) {
    var dataReq = {};
    if (json) {
      dataReq = Mock.mock(json).req || {}
    }
    dataArr.push(dataReq);
  }

  utils.axios(base, api, dataArr, 'POST', number)
      .then((r) => {
        var reqList = [];
        var resList = [];
        for (var i = 0; i < dataArr.length; i++) {
          var reqData = dataArr[i] || {}
          var reqDataHtml = utils.mockJsonHtml(reqData)
          reqList.push(reqDataHtml)
        }
        for (var i = 0; i < r.length; i++) {
          var resData = r[i].data || {}
          var resDataHtml = utils.mockJsonHtml(resData)
          resList.push(resDataHtml)
        }
        var obj = {
          postData: reqList,
          getData: resList,
        }

        res.setHeader('content-type', 'application/json;charset=utf8')
        res.send(obj);
      })
      .catch((error) => {
        var reqList = []
        var resList = []
        var config = error.config || {}
        var reqData = config.data || {}
        if (reqData && typeof reqData == 'string') {
          reqData = reqData.trim();
          reqData = JSON.parse(reqData) ? JSON.parse(reqData) : eval('(' + reqData + ')');
        }
        var reqDataHtml = utils.mockJsonHtml(reqData)
        reqList.push(reqDataHtml)
        var status = error && error.response && error.response.status ? error.response.status : error
        resList.push(status)
        var obj = {
          postData: reqList,
          getData: resList,
        }
        res.setHeader('content-type', 'application/json;charset=utf8')
        res.send(obj)
      })
})

app.post('/login', function (req, res) {

  var base = req.body.base
  var api = req.body.api
  var username = req.body.username
  var password = req.body.password

  var dataArr = []
  var loginData = {
    mobile: username,
    password: password,
  }
  dataArr.push(loginData);

  utils.axios(base, api, dataArr, 'POST', 1)
      .then((r) => {
        var resData = {}
        if (r.length > 0) {
          resData = r[0].data || {}
        }
        res.setHeader('content-type', 'application/json;charset=utf8')
        res.send(resData)
      })
      .catch((error) => {
        var status = error && error.response && error.response.status ? error.response.status : error
        res.setHeader('content-type', 'application/json;charset=utf8')
        res.send(status)
      })

})

app.listen(port)
